/**
 * 
 */
package miningMinds;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;

import parameter.*;
import functions.*;

/**
 * @author kjysmu
 *
 */
public class SNSLoader {
	
	String path_sns;
	String path_tc;
	Double averageSimilarity;
	Double averageMsgAccuracy;

	Map<String, SNSUserBean> userMap;
	Map<String, String> msgTermCountsStrMap;

	public SNSLoader(String SNStype){
		if(SNStype.equals("Facebook")){
			path_sns = Path.FACEBOOK_LABEL_RESULT_PATH;
			path_tc = Path.FACEBOOK_LABEL_RESULT_TERMCOUNT_PATH;
		}else if(SNStype.equals("Twitter")){
			path_sns = Path.TWITTER_LABEL_RESULT_PATH;
			path_tc = Path.TWITTER_LABEL_RESULT_TERMCOUNT_PATH;
		}
		init();
	}
	
	public void init(){
		msgTermCountsStrMap = new HashMap<String, String>();
		userMap = new HashMap<String, SNSUserBean>();
		SNSUserBean userBean = new SNSUserBean();
		try{
			FileReader fr_TermCounts = new FileReader(new File(path_tc));
			BufferedReader br_TermCounts = new BufferedReader(fr_TermCounts);
			String lineTC = "";
			while (true) {
				lineTC = br_TermCounts.readLine();
				if (lineTC == null) break;
				
				StringTokenizer stringTokenizer = new StringTokenizer(lineTC, "\t");
				if (stringTokenizer.countTokens() == 2) {
					String token1 = stringTokenizer.nextToken();
					String token2 = stringTokenizer.nextToken();
					msgTermCountsStrMap.put(token1, token2);
				}
			}
			br_TermCounts.close();
			fr_TermCounts.close();
			
			FileReader fr = new FileReader(path_sns);
			BufferedReader br = new BufferedReader(fr);
			String line = "";
			Boolean isFst = true;
			Boolean isUID = false;
			String userID;
			
			while(true){
				line = br.readLine();
				if( line == null ){
					if(isUID){
						userMap.put(userBean.getUserid(), userBean);
						// Add previous data 
					}
					break;
				}
				if( line.startsWith("// UserID")  ){
					isUID = true;
					if( isFst ){
						isFst = false;
					}else{
						userMap.put(userBean.getUserid(), userBean);
					} // Add previous data
					userBean = new SNSUserBean();
					userID = line.substring(11);
					userBean.setUserid(userID);
					
				}else{
					StringTokenizer st = new StringTokenizer(line,"\t");
					
					int stcount = st.countTokens();
					if(stcount == 7){
						
						Map<String, Double> msgTermCounts = new HashMap<String,Double>();
						
						SNSUserMsgBean userMsgBean = new SNSUserMsgBean();
						
						String tokenid = st.nextToken();
						String token = st.nextToken();
						String msg = token.replaceAll("[\\s]", " ");
	
						String t_time = st.nextToken();
						String t_category1 = st.nextToken().replaceAll("/", "").replaceAll(" ", "");
						String t_category2 = st.nextToken().replaceAll("/", "").replaceAll(" ", "");
						String t_category3 = st.nextToken().replaceAll("/", "").replaceAll(" ", "");
						String t_category4 = st.nextToken().replaceAll("/", "").replaceAll(" ", "");
	
						userMsgBean.setMsgid(tokenid);
						userMsgBean.setTime(t_time);
						userMsgBean.setMsg(msg);
						
						if(!t_category1.equals("NONE") && !t_category2.equals("NONE")){
							userMsgBean.addLabelCategoryMap(t_category1 + " " + t_category2);
						}
						if(!t_category3.equals("NONE") && !t_category4.equals("NONE")){
							userMsgBean.addLabelCategoryMap(t_category3+ " " + t_category4);
						}
						//msgTermCounts = TweetFunction.GetTermCounts(msg, kom);
						
						msgTermCounts = TermFunction.convertTermCountMap(msgTermCountsStrMap.get(tokenid));
						userBean.appendTotalTermCount(msgTermCounts);						
						userMsgBean.setTermCountMap(msgTermCounts);
						userBean.addMsgMap(tokenid, userMsgBean);
						
					}//end of stcount IF

				}

			}
			
			br.close();
			fr.close();
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
	}
	
	public Map<String, SNSUserBean> getUserMap(){
		return userMap;
	}
	public void generateResultHTML() throws Exception{
		
		Map<String, String> comparisonResultMap = new HashMap<String, String>();
		
		if(Exp.isComparisonResults){
			FileReader fr_comp = new FileReader(new File(Path.RESULT_COMPARISON_FILEPATH));
			BufferedReader br_comp = new BufferedReader(fr_comp);
			String line_comp = "";
			while (true) {
				line_comp = br_comp.readLine();
				if (line_comp == null) break;
				StringTokenizer stringTokenizer = new StringTokenizer(line_comp, "\t");
				if (stringTokenizer.countTokens() == 2) {
					String key = stringTokenizer.nextToken();
					String value = stringTokenizer.nextToken();
					comparisonResultMap.put(key, value);
				}
			}
			br_comp.close();
			fr_comp.close();
		}
		
		for (Entry<String, SNSUserBean> userMapEntry : userMap.entrySet()) {
			String userid = userMapEntry.getKey();
			SNSUserBean userBean = userMapEntry.getValue();
			
			File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
			if(!dir.exists()) dir.mkdir();
			File dir2 = new File(dir.getCanonicalPath(), Exp.resultPathTestAppend);
			if(!dir2.exists()) dir2.mkdir();
			
			File dir_page = new File(dir2.getCanonicalPath(), "resultPage" );
			if(!dir_page.exists()) dir_page.mkdir();
			
			FileWriter fw_res = new FileWriter( dir_page.getCanonicalPath()+"\\" +userBean.getUserid()+".html" );
			BufferedWriter writer_res = new BufferedWriter(fw_res);
			
			writer_res.write("<html>\n");
			writer_res.write("<head>\n");
			writer_res.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n");
			writer_res.write("<title>Recommendation Result</title>\n");
			writer_res.write("</head>\n");
			writer_res.write("<body>\n");
			
			Map<String, SNSUserMsgBean> msgMap = userBean.getMsgMap();
			
			for (Entry<String, SNSUserMsgBean> msgMapEntry : msgMap.entrySet()) {
				String msgMapKey = msgMapEntry.getKey();
				SNSUserMsgBean msgMapValue = msgMapEntry.getValue();
				Map<String, Double> msgTermCounts = msgMapValue.getTermCountMap();
				Map<String, Double> labelCategoryMap = msgMapValue.getLabelCategoryMap();
				Map<String, Double> recomCategoryMap = msgMapValue.getRecomCategoryMap();
				Map<String, Double> recomTotalCategoryMap = msgMapValue.getRecomTotalCategoryMap();
				Map<String, Double> msgWikiCategoryMap = msgMapValue.getWikiCategoryMap();
				List<SNSTermBean> termList = msgMapValue.getTermList();
				
				writer_res.write("<table width=\"1000\" height=\"100\" border=\"1\">\n");
				writer_res.write("<tr>\n");
				writer_res.write("<td height=\"10\" colspan=\"3\">" + "Msg ID : "+ msgMapValue.getMsgid() + "</td>\n");
				writer_res.write("</tr>\n");
				/*-------------------------------------------------------------------------------------------------------*/
				// RAW MSG
				writer_res.write("<tr>\n");
				writer_res.write("<td height=\"60\" colspan=\"3\">" + msgMapValue.getMsg() + "</td>\n");
				writer_res.write("</tr>\n");
				
				/*-------------------------------------------------------------------------------------------------------*/
				// Result Analysis Detail 
				if(Exp.approach.contains("wiki") && Exp.isResultAnalysis){
					for(SNSTermBean termBean : termList){
						writer_res.write("<tr>\n");
						writer_res.write("<td width=\"300\"><small>\n");
						writer_res.write("<b>term</b> : "+termBean.getTerm() + "</small></td><td colspan=\"2\"><small>");
						if(termBean.isRedirect()) writer_res.write("<b>rediretedTerm</b> : "+termBean.getRedirectTerm() +" ");
						writer_res.write("<b>tf</b> : "+ String.format("%.2f", termBean.getTF()) + " ");
						writer_res.write("<b>idf</b> : "+ String.format("%.2f", termBean.getIDF()) + " ");
						if(termBean.isHomonym()){
							List<SNSTermBean> homonymTermList = termBean.getHomonymTermList();
							writer_res.write("<b>homonymTerms</b> : ");
							String hmlist_str = "";
							for(SNSTermBean homonymTermBean : homonymTermList){
								if(!hmlist_str.equals("")) hmlist_str +=" , ";;
								hmlist_str += homonymTermBean.getTerm();
							}
							writer_res.write( hmlist_str + " \n");
						}
						if(termBean.isWikiCategory()){
							Map<String, Double> termWikiCategoryMap = termBean.getWikiCategoryMap();
							writer_res.write("<b>wikiCategory</b> : ");
							String wclist_str = "";
							for (Entry<String, Double> entry : termWikiCategoryMap.entrySet()) {
								String key = entry.getKey();
								Double value = entry.getValue();
								if(!wclist_str.equals("")) wclist_str +=" , ";;
								wclist_str += key +"(" + String.format("%.2f", value) + ")";
							}
							writer_res.write( wclist_str + "\n");
						}
						writer_res.write("</small></td>\n");
						writer_res.write("</tr>\n");
					}
				}else{
					/*-------------------------------------------------------------------------------------------------------*/
					// TermCounts Results
					writer_res.write("<tr>\n");
					writer_res.write("<td colspan=\"3\">");
					
					for(Map.Entry<String, Double> msgTermCount : msgTermCounts.entrySet()){
						writer_res.write(msgTermCount.getKey() + "(" + String.format("%.2f",msgTermCount.getValue()) +")"+ " ");
					}
					
					writer_res.write("</td>\n");
					writer_res.write("</tr>\n");
				}
				
	
				/*-------------------------------------------------------------------------------------------------------*/
				// WikiCategory (MSG) Results
				if(Exp.approach.contains("wiki")){
					writer_res.write("<tr>\n");
					writer_res.write("<td colspan=\"3\"><small>");
					DoubleValueComparator doubleValueComparator = new DoubleValueComparator(msgWikiCategoryMap);
					TreeMap<String, Double> treeMap = new TreeMap<String, Double>(doubleValueComparator);
					treeMap.putAll(msgWikiCategoryMap);
					writer_res.write("<b>Total wikiCategory</b> : ");
					for(Map.Entry<String, Double> entry : treeMap.entrySet()){
						if(entry.getValue() <= 0.00 ) writer_res.write("<strike>");
						writer_res.write(entry.getKey() + "(" + String.format("%.2f",entry.getValue()) +")"+ " ");
						if(entry.getValue() <= 0.00 ) writer_res.write("</strike>");
					}
					writer_res.write("<small></td>\n");
					writer_res.write("</tr>\n");
				}
				
				/*-------------------------------------------------------------------------------------------------------*/
				// User-Labeled Category
				writer_res.write("<tr>\n");
				writer_res.write("<td width=\"200\" height=\"60\">");
				for(Map.Entry<String, Double> labelCategoryMapEntry : labelCategoryMap.entrySet()){
					writer_res.write("<p>"+ labelCategoryMapEntry.getKey() +"</p>");
				}
				writer_res.write("</td>\n");
				
				// Recommended Category
				writer_res.write("<td width=\"450\">");
				DoubleValueComparator bvc = new DoubleValueComparator(recomTotalCategoryMap);
				TreeMap<String, Double> tMap = new TreeMap<String, Double>(bvc);
				tMap.putAll(recomTotalCategoryMap);
				
				int ct = 0;
				for(Map.Entry<String, Double> TCMapEntry : tMap.entrySet()){
					if( ct >= Exp.categoryDebugNum ) break;
					if(recomCategoryMap.containsKey(TCMapEntry.getKey())){
						if( labelCategoryMap.containsKey(TCMapEntry.getKey()) ){
							writer_res.write("<font color=\"#0066FF\"><strong>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strong></font>\n");
						}else{
							writer_res.write("<font color=\"#CC0000\"><strong>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strong></font>\n");
						}
					}else{
						if( labelCategoryMap.containsKey(TCMapEntry.getKey()) ){
							writer_res.write("<font color=\"#0066FF\"><strike>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strike></font>\n");
						}else{
							writer_res.write("<font color=\"#CC0000\"><strike>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strike></font>\n");
						}
					}
					ct++;
				}
				writer_res.write("</td>\n");
				
				if(Exp.isComparisonResults){
					
					writer_res.write("<td width=\"450\" bgcolor=\"#BBBBBB\">");
					String compCategoryResultStr = comparisonResultMap.get(msgMapValue.getMsgid());
					Map<String, Double> compCategoryResultMap = TermFunction.convertTermCountMap(compCategoryResultStr);

					bvc = new DoubleValueComparator(compCategoryResultMap);
					tMap = new TreeMap<String, Double>(bvc);
					tMap.putAll(compCategoryResultMap);
					
					for(Map.Entry<String, Double> TCMapEntry : tMap.entrySet()){
						if( labelCategoryMap.containsKey(TCMapEntry.getKey()) ){
							writer_res.write("<font color=\"#0066FF\"><strike>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strike></font>\n");
						}else{
							writer_res.write("<font color=\"#CC0000\"><strike>\n");
							writer_res.write("<p>"+ TCMapEntry.getKey() + " ("+ String.format("%.6f",TCMapEntry.getValue())+  ")"+"</p>\n");
							writer_res.write("</strike></font>\n");
						}
					}
					writer_res.write("</td>\n");
				}
				
				writer_res.write("</tr>\n");
				writer_res.write("</table>\n");
				writer_res.write("<br />\n");
				
			}
			
			writer_res.write("<tr>\n");
			writer_res.write("<td height=\"60\" colspan=\"2\">" + "Similarity:"+ String.format("%.4f", userBean.getSimilarity()) + "</td>\n");
			writer_res.write("</tr>\n");
			writer_res.write("</table>\n");
			writer_res.write("</body>\n");
			writer_res.write("</html>\n");
			
			writer_res.close();
			fw_res.close();
			
		}
	}
	
	public void generateResultFile() throws Exception{
		
		File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
		if(!dir.exists()) dir.mkdir();
		File dir2 = new File(dir.getCanonicalPath(), Exp.resultPathTestAppend);
		if(!dir2.exists()) dir2.mkdir();
		
		FileWriter fw_res = new FileWriter(dir2.getCanonicalPath() +"\\similarity.txt");
		BufferedWriter writer_res = new BufferedWriter(fw_res);
		
		double totalSim = 0.0;
		for (Entry<String, SNSUserBean> userMapEntry : userMap.entrySet()) {
			String userid = userMapEntry.getKey();
			SNSUserBean userBean = userMapEntry.getValue();
			double sim = userBean.getSimilarity();
			totalSim+=sim;
			writer_res.write(String.format("%.4f", sim));
			writer_res.newLine();	
		}
		writer_res.newLine();
		double avrSim = totalSim / userMap.size();
		writer_res.write(String.format("%.4f", avrSim ));
		
		writer_res.close();
		fw_res.close();
		
		averageSimilarity = avrSim;
		
	}
	
	public void generateMsgAccuracyResultFile() throws Exception{
		
		File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
		if(!dir.exists()) dir.mkdir();
		File dir2 = new File(dir.getCanonicalPath(), Exp.resultPathTestAppend);
		if(!dir2.exists()) dir2.mkdir();
		
		FileWriter fw_res = new FileWriter(dir2.getCanonicalPath() +"\\msg_accuracy.txt");
		BufferedWriter writer_res = new BufferedWriter(fw_res);
		
		double totalAcc = 0.0;
		for (Entry<String, SNSUserBean> userMapEntry : userMap.entrySet()) {
			String userid = userMapEntry.getKey();
			SNSUserBean userBean = userMapEntry.getValue();
			double accuracy = userBean.getMsgAccuracy();
			totalAcc+=accuracy;
			writer_res.write(String.format("%.4f", accuracy));
			writer_res.newLine();	
		}
		writer_res.newLine();
		double avrAcc = totalAcc / userMap.size();
		writer_res.write(String.format("%.4f", avrAcc ));
		
		writer_res.close();
		fw_res.close();
		
		averageMsgAccuracy = avrAcc;
		
	}
	
	
	public void generateRecomCategoryResultFile() throws Exception{
		
		File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
		if(!dir.exists()) dir.mkdir();
		File dir2 = new File(dir.getCanonicalPath(), Exp.resultPathTestAppend);
		if(!dir2.exists()) dir2.mkdir();
		
		FileWriter fw_res = new FileWriter(dir2.getCanonicalPath() +"\\recomCategoryResults.txt");
		BufferedWriter writer_res = new BufferedWriter(fw_res);
		for (Entry<String, SNSUserBean> userMapEntry : userMap.entrySet()) {
			SNSUserBean userBean = userMapEntry.getValue();
			Map<String, SNSUserMsgBean> userMsgBean = userBean.getMsgMap();
			for (Entry<String, SNSUserMsgBean> entry : userMsgBean.entrySet()) {
				String key = entry.getKey();
				SNSUserMsgBean value = entry.getValue();
				Map<String, Double> recomCategoryMap = value.getRecomCategoryMap();
				String recomCategoryStr = TermFunction.convertMapSDToStr(recomCategoryMap, "#", "&", "%.6f");
				if(recomCategoryStr.trim().equals("")) recomCategoryStr = "NONE";
				writer_res.write(key + "\t" + recomCategoryStr);
				writer_res.newLine();
			}
		}		
		writer_res.close();
		fw_res.close();
		
	}
	
	public void generateParameterFile() throws Exception{
		
		File dir = new File(Path.RESULT_PATH, Exp.resultPathAppend);
		if(!dir.exists()) dir.mkdir();
		File dir2 = new File(dir.getCanonicalPath(), Exp.resultPathTestAppend);
		if(!dir2.exists()) dir2.mkdir();
		
		FileWriter fw_res = new FileWriter(dir2.getCanonicalPath() +"\\parameter.txt");
		BufferedWriter writer_res = new BufferedWriter(fw_res);
		
		writer_res.write("SNSType : "+Exp.SNSType);
		writer_res.newLine();
		writer_res.write("approach : "+Exp.approach);
		writer_res.newLine();
		writer_res.write("msg_threshold : "+Exp.msg_threshold);
		writer_res.newLine();
		writer_res.write("msg_threshold2 : "+Exp.msg_threshold2);
		writer_res.newLine();
		writer_res.write("msg_maxcategory : "+Exp.msg_maxcategory);
		writer_res.newLine();
		writer_res.write("isWikiIDF : "+Exp.isWiki_NaverIDF);
		writer_res.newLine();
		writer_res.write("wiki_topic_path : "+Exp.wiki_topic_path);
		writer_res.newLine();
		writer_res.write("str_LDAmodel : "+Exp.str_LDAmodel);
		writer_res.newLine();
		writer_res.write("WORD_FREQUENCY_THRESHOLD : "+ String.format("%.8f", Exp.WORD_FREQUENCY_THRESHOLD) );
		writer_res.newLine();
		writer_res.newLine();
		writer_res.write("Version REMARK : "+ Exp.versionRemark );
		writer_res.newLine();
		
		writer_res.close();
		fw_res.close();
	}
	
	public double getAverageSimilarity(){
		return averageSimilarity;
	}
	public double getAverageMsgAccuracy(){
		return averageMsgAccuracy;
	}


	
	
	
	
}
